Skip to content

feat(aio): add system one boolean judges with shared egress - #103752

Open
bernatixer wants to merge 43 commits into
rafa/ts-4b-system-one-clientfrom
feat/aio-jev-boolean-evaluations
Open

bernatixer wants to merge 43 commits into
rafa/ts-4b-system-one-clientfrom
feat/aio-jev-boolean-evaluations

Conversation

@bernatixer

@bernatixer bernatixer commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Problem

AI observability users need to run boolean evaluations against a System One-compatible model they configure themselves.
This PR builds on #106735, which provides the shared protocol types, parser, and HTTP client.

Changes

  • Users can add a System One connection with an HTTPS endpoint, model ID, and optional bearer token. The form has no hosted endpoint or model default.
  • Connection validation sends a synthetic question. Evaluation calls use the saved endpoint and credential, with no instance credential fallback.
  • The feature flag gates validation and evaluation runs. Turning it off skips queued runs without calling the endpoint.
  • The client rejects private destinations, redirects, and the hosted TypeSafe endpoint. A rejected input skips its run without invalidating a shared connection.
  • Boolean judges turn a Noul probability into a result. Numeric and categorical mapping remain separate.
  • Events keep the configured model ID and available token usage. Cost stays unknown when the model has no catalog price; the pinned Jev price is removed.
  • Cosmetic edits to a connection URL preserve its saved bearer token. Connection validation uses a shorter timeout.
  • System One remains unavailable to completion-based surfaces such as Playground and taggers.
  • Generated API types and provider identifiers are mechanical updates.

Before:

flowchart LR
    A[LLM judge evaluation] --> B[Completion provider] --> C[Boolean or numeric result]
    classDef phYellow fill:#f9bd2b,stroke:#f9bd2b,color:#000;
    classDef phRed fill:#f54e00,stroke:#f54e00,color:#fff;
    class A,C phYellow;
    class B phRed;
Loading

After:

flowchart LR
    A[LLM judge evaluation] --> B[Completion provider] --> C[Boolean or numeric result]
    A --> D[System One connection] --> E[Shared egress client] --> F[Compatible endpoint] --> G[Boolean result and probability]
    classDef phYellow fill:#f9bd2b,stroke:#f9bd2b,color:#000;
    classDef phRed fill:#f54e00,stroke:#f54e00,color:#fff;
    classDef phBlue fill:#1d4aff,stroke:#1d4aff,color:#fff;
    class A,C,G phYellow;
    class B,F phRed;
    class D,E phBlue;
Loading
Existing judge details System One boolean details
Existing judge details System One probability

The connection form at 520px replaces the earlier screenshots that showed hosted defaults:

System One connection fields

How did you test this code?

  • Backend tests cover endpoint validation, no-auth connections, credential replacement, response parsing, boolean thresholds, and evaluation error handling. The evaluation test file passed (165 tests).
  • Frontend tests cover provider labels, model selection, and probability display. The frontend type check and OpenAPI generation passed.
  • The ingestion cost test confirms no pinned Jev price. Strict CI preflight passed.
  • Storybook rendered the connection fields at 520px and 1000px with invented placeholders.
  • Live calls to a compatible System One deployment remain unchecked; protocol tests use mocked HTTP responses.

👉 Stay up-to-date with PostHog coding conventions for a smoother review.

Release status

  • No feature flag controls this change
  • This change is behind a feature flag and is not available to users
  • This change makes a previously flagged feature available to everyone

The llm-analytics-system-one-evaluations flag defaults off. Deploy ingestion and evaluation workers before enabling it.

Automatic notifications

  • Publish to changelog?

Docs update

Updated AI observability judge inputs with connection settings, result semantics, and compatibility limits.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Agent: Codex, GPT-6

The existing CodeRabbit CLI pass identified rejected requests classified as unreadable output; the evaluation error handling and regression tests address it.
CodeRabbit's GitHub review also identified shared-key invalidation and endpoint-controlled metric labels. Both are addressed in the current code.
Public examples and screenshots use invented values. The session has no shareable link.

Tools: shell, Git, GitHub CLI, hogli, Playwright, and web documentation.
Repository skills: stacking-prs, writing-pr-descriptions, running-ci-preflight, reviewing-with-coderabbit, routing-outbound-api-calls, writing-tests, writing-ui-components, writing-user-facing-copy, and adopting-generated-api-types.
Public skills: Boffin, Ponytail, and Superpowers brainstorming, test-driven-development, and verification-before-completion.

@bernatixer bernatixer self-assigned this Sep 21, 2026
@trunk-io

trunk-io Bot commented Sep 21, 2026

Copy link
Copy Markdown

Merging to master in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

github-actions Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

⚠️ Trunk lane — backend Python lane

This PR is assigned to the backend Python lane. It runs backend Python tests and may merge in parallel with PRs in other lanes.

⚠️ Complexity (TypeScript) — 20 functions above the limit (max 115)

Cyclomatic complexity above the limit in changed typescript files (10 for production files, 15 for test files). Warn only: worth simplifying when you next touch these functions.

Function Location Complexity Limit
AIObservabilityEvaluation products/ai_observability/frontend/evaluations/AIObservabilityEvaluation.tsx:78 115 10
EditKeyModal products/ai_observability/frontend/settings/LLMProviderKeysSettings.tsx:424 26 10
AddKeyModal products/ai_observability/frontend/settings/LLMProviderKeysSettings.tsx:169 19 10
normalizeLLMProvider products/ai_observability/frontend/settings/llmProviderKeysLogic.ts:68 16 10
normalizeEvaluationResultProperties products/ai_observability/frontend/utils.ts:1188 16 10
queryEvaluationRunsStats products/ai_observability/frontend/utils.ts:1357 16 10
getGeminiInlineData products/ai_observability/frontend/utils.ts:838 15 10
looksLikeXml products/ai_observability/frontend/utils.ts:1074 15 10
isToolStepItem products/ai_observability/frontend/utils.ts:628 13 10
isAnthropicImageMessage products/ai_observability/frontend/utils.ts:798 13 10
isAnthropicDocumentMessage products/ai_observability/frontend/utils.ts:816 13 10
parseToolArgumentsForDisplay products/ai_observability/frontend/utils.ts:967 13 10
EvaluationRunsTable products/ai_observability/frontend/evaluations/components/EvaluationRunsTable.tsx:43 12 10
handleSubmit products/ai_observability/frontend/settings/LLMProviderKeysSettings.tsx:450 12 10
formatLLMEventTitle products/ai_observability/frontend/utils.ts:1026 12 10
queryEvaluationRuns products/ai_observability/frontend/utils.ts:1276 12 10
getKeyPlaceholder products/ai_observability/frontend/settings/LLMProviderKeysSettings.tsx:90 11 10
DeleteKeyModal products/ai_observability/frontend/settings/LLMProviderKeysSettings.tsx:606 11 10
LLMProviderKeysSettings products/ai_observability/frontend/settings/LLMProviderKeysSettings.tsx:721 11 10
isOpenAIFileMessage products/ai_observability/frontend/utils.ts:771 11 10
✅ Duplication (Python) — clean

New Python code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

✅ Duplication (TypeScript) — clean

New TypeScript code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

⚠️ Bundle size — 🔺 +4.8 KiB (+0.0%)

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 68.82 MiB · 🔺 +4.8 KiB (+0.0%)

File Size Δ vs base
render-query/src/render-query/render-query.js 20.24 MiB 🔺 +1.6 KiB (+0.0%)

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

✅ Eager graph — within budget

How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1.57 MiB · 22 files no change █████████░ 85.1% of 1.84 MiB
logged-out boot: index + App + bootApp (preloaded by every page, including /login)
src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
3.57 MiB · 628 files 🔺 +76 B (+0.0%) █████████░ 88.6% of 4.03 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
7.27 MiB · 2,301 files 🔺 +408 B (+0.0%) █████████░ 87.2% of 8.34 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 [object Object] stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/layout/navigation-3000/navigationLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/dashboard/dashboardLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/lemon-ui/LemonMarkdown/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/RichContentEditor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/CodeSnippet/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/taxonomy/core-filter-definitions-by-group.json stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx
🟢 [object Object] stays out of src/scenes/AuthenticatedShell.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
4.5 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
3.9 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.4 KiB ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
1.3 KiB src/index.tsx
1.3 KiB src/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
854 B src/scenes/ChunkLoadErrorBoundary.tsx
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
Size File
301.8 KiB ../node_modules/.pnpm/posthog-js@1.434.13_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
267.6 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
100.4 KiB src/lib/api.ts
84.9 KiB src/products.tsx
69.1 KiB src/lib/lemon-ui/icons/icons.tsx
63.9 KiB src/lib/utils/eventUsageLogic.ts
38.7 KiB ../node_modules/.pnpm/@dnd-kit+core@6.0.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js
33.9 KiB ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js
28.3 KiB src/scenes/scenes.ts
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
301.8 KiB ../node_modules/.pnpm/posthog-js@1.434.13_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
272.0 KiB src/taxonomy/core-filter-definitions-by-group.json
267.6 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.7 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
100.4 KiB src/lib/api.ts
98.5 KiB ../packages/quill/packages/quill/dist/index.js
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
90.6 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
84.9 KiB src/products.tsx

Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479

✅ Toolbar bundle — eager 2.37 MiB within budget

What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.

Metric Size Δ vs base Budget
Eager (shipped)
entry + static imports
2.37 MiB · 19 files 🔺 +76 B (+0.0%) ████░░░░░░ 41.4% of 5.72 MiB
Deferred (lazy) 2.10 MiB · 44 files 🔺 +332 B (+0.0%) n/a — loads on demand
Loader dist/toolbar.js 1.2 KiB no change █░░░░░░░░░ 6.0% of 19.5 KiB
Largest eagerly-shipped chunks
Size File
790.2 KiB dist/toolbar/toolbar-app-ZNXS4H6W.css
650.5 KiB dist/toolbar/chunk-chunk-SCJBJUCD.js
483.6 KiB dist/toolbar/chunk-chunk-DPLA2GAY.js
138.3 KiB dist/toolbar/chunk-chunk-VUAOBILF.js
131.8 KiB dist/toolbar/chunk-chunk-FDH2IBXT.js
75.2 KiB dist/toolbar/toolbar-app-X75LXL7Z.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-ECAITW5Z.js
21.0 KiB dist/toolbar/chunk-chunk-P7KVYVSM.js
6.8 KiB dist/toolbar/chunk-chunk-DV7IWQNF.js

Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile

✅ Dist folder size — 🔺 +79.9 KiB (+0.0%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 943.60 MiB · 🔺 +79.9 KiB (+0.0%)

ℹ️ MCP UI apps size — 33 app(s), 17628.2 KB JS

Built size of each MCP UI app (main.js + styles.css).

App JS CSS
debug 597.8 KB 196.2 KB
action 454.1 KB 196.2 KB
action-list 564.1 KB 196.2 KB
cohort 453.1 KB 196.2 KB
cohort-list 563.1 KB 196.2 KB
email-template 452.9 KB 196.2 KB
error-details 469.1 KB 196.2 KB
error-issue 453.8 KB 196.2 KB
error-issue-list 564.0 KB 196.2 KB
experiment 561.2 KB 196.2 KB
experiment-list 564.9 KB 196.2 KB
experiment-results 566.2 KB 196.2 KB
feature-flag 566.7 KB 196.2 KB
feature-flag-list 570.5 KB 196.2 KB
feature-flag-testing 457.3 KB 196.2 KB
inline-scan 453.6 KB 196.2 KB
insight-actors 562.3 KB 196.2 KB
invite-email-preview 452.3 KB 196.2 KB
llm-costs 559.3 KB 196.2 KB
session-recording 454.9 KB 196.2 KB
survey 454.7 KB 196.2 KB
survey-global-stats 561.8 KB 196.2 KB
survey-list 564.8 KB 196.2 KB
survey-stats 561.8 KB 196.2 KB
trace-span 453.5 KB 196.2 KB
trace-span-list 564.0 KB 196.2 KB
vision-observation-list 563.2 KB 196.2 KB
workflow 453.4 KB 196.2 KB
workflow-list 563.5 KB 196.2 KB
loops-review 457.8 KB 196.2 KB
query-results 774.0 KB 196.2 KB
render-ui 856.5 KB 196.2 KB
visual-review-snapshots 457.9 KB 196.2 KB
✅ Playwright — all passed

All tests passed.

View test results →

⚠️ Backend coverage — 91.0% of changed backend lines covered — 107 uncovered

🧪 Backend test coverage

Patch coverage — changed backend lines (products + core): ██████████████████░░ 91.0% (1,199 / 1,306)

File Patch Uncovered changed lines
products/ai_observability/backend/models/model_configuration.py 0.0% 63
products/ai_observability/backend/llm/client.py 42.9% 92–93, 99–100
products/tasks/backend/facade/task_run_signals.py 75.0% 25
products/ai_observability/backend/api/test/test_provider_keys.py 75.4% 280–283, 298–311, 314–319, 322–328
posthog/egress/typesafe/transport.py 83.3% 36, 39, 42
products/tasks/backend/facade/api.py 83.5% 709–710, 725, 727–732, 734–738, 4542–4544, 4549, 4552–4553, 4593, 4640
posthog/security/pinned_aiohttp.py 86.7% 21, 34
products/posthog_ai/backend/exec_commands.py 87.2% 51, 60, 69, 73, 81–82
products/ai_observability/backend/llm/system_one.py 88.2% 37–38, 74–78, 99–100, 130, 147, 157
products/ai_observability/backend/api/provider_keys.py 89.4% 203, 310–315
posthog/llm/system_one_client.py 90.0% 85–86, 103–106, 143–145
products/tasks/backend/models.py 92.6% 981, 985
products/signals/backend/facade/api.py 94.4% 1192
posthog/egress/typesafe/client.py 96.7% 104–105
posthog/llm/system_one.py 96.9% 75, 146, 174
posthog/egress/test/test_typesafe.py 99.1% 235

🤖 Agents: add a test covering the lines above, or note why under "How did you test this code?". Machine-readable gap list: the patch-coverage artifact on this run (gh run download 36490601971 -n patch-coverage), or the coverage-data block at the end of this comment.

Per-product line coverage (touched products)
Product Coverage Lines
platform_features ██░░░░░░░░░░░░░░░░░░ 12.1% 7 / 58
warehouse_sources_queue ██████░░░░░░░░░░░░░░ 29.1% 92 / 316
demo ████████████░░░░░░░░ 57.9% 1,547 / 2,673
data_tools ████████████░░░░░░░░ 61.2% 90 / 147
aeo ██████████████░░░░░░ 70.5% 467 / 662
ai_gateway ███████████████░░░░░ 75.0% 9 / 12
batch_exports ████████████████░░░░ 81.2% 21,452 / 26,424
apm █████████████████░░░ 84.1% 1,306 / 1,553
ml_inference █████████████████░░░ 86.7% 451 / 520
cdp ██████████████████░░ 88.2% 4,548 / 5,155
mcp_analytics ██████████████████░░ 88.6% 4,704 / 5,308
signals ██████████████████░░ 88.7% 52,451 / 59,133
product_tours ██████████████████░░ 89.3% 1,331 / 1,491
dashboards ██████████████████░░ 89.8% 7,234 / 8,056
data_warehouse ██████████████████░░ 89.9% 13,738 / 15,285
cohorts ██████████████████░░ 90.2% 8,238 / 9,138
notebooks ██████████████████░░ 90.2% 15,287 / 16,945
streamlit_apps ██████████████████░░ 90.7% 2,625 / 2,895
managed_warehouse ██████████████████░░ 90.9% 10,215 / 11,234
tasks ██████████████████░░ 91.1% 73,926 / 81,124
data_modeling ██████████████████░░ 91.4% 10,491 / 11,483
business_knowledge ██████████████████░░ 91.6% 6,899 / 7,528
engineering_analytics ██████████████████░░ 91.7% 11,002 / 11,999
exports ██████████████████░░ 91.8% 9,685 / 10,555
ai_training ██████████████████░░ 92.2% 356 / 386
conversations ███████████████████░ 92.5% 28,705 / 31,025
early_access_features ███████████████████░ 92.6% 1,341 / 1,448
managed_migrations ███████████████████░ 92.7% 1,581 / 1,705
visual_review ███████████████████░ 92.8% 9,244 / 9,966
canvas ███████████████████░ 92.8% 6,877 / 7,409
approvals ███████████████████░ 93.0% 3,919 / 4,214
mcp_registry ███████████████████░ 93.1% 1,670 / 1,794
error_tracking ███████████████████░ 93.1% 15,708 / 16,874
notifications ███████████████████░ 93.2% 1,145 / 1,229
slack_app ███████████████████░ 93.2% 13,677 / 14,674
surveys ███████████████████░ 93.3% 6,571 / 7,040
stamphog ███████████████████░ 93.4% 7,716 / 8,262
context_layer ███████████████████░ 93.8% 3,373 / 3,595
ai_observability ███████████████████░ 93.9% 20,938 / 22,293
web_analytics ███████████████████░ 93.9% 21,653 / 23,051
alerts ███████████████████░ 94.1% 8,553 / 9,094
billing_alerts ███████████████████░ 94.1% 2,094 / 2,226
mcp_store ███████████████████░ 94.4% 8,940 / 9,472
wizard ███████████████████░ 94.4% 5,791 / 6,134
reminders ███████████████████░ 94.8% 760 / 802
workflows ███████████████████░ 94.8% 13,438 / 14,170
review_hog ███████████████████░ 94.9% 11,490 / 12,109
annotations ███████████████████░ 95.1% 817 / 859
customer_analytics ███████████████████░ 95.1% 24,669 / 25,932
endpoints ███████████████████░ 95.1% 9,211 / 9,681
legal_documents ███████████████████░ 95.2% 2,311 / 2,427
marketing_analytics ███████████████████░ 95.3% 19,047 / 19,991
posthog_ai ███████████████████░ 95.4% 2,489 / 2,610
logs ███████████████████░ 95.4% 15,235 / 15,967
tracing ███████████████████░ 95.4% 3,483 / 3,650
growth ███████████████████░ 95.4% 9,812 / 10,282
actions ███████████████████░ 95.5% 756 / 792
messaging ███████████████████░ 95.9% 3,766 / 3,927
skills ███████████████████░ 95.9% 6,649 / 6,932
replay_vision ███████████████████░ 96.0% 26,750 / 27,878
autoresearch ███████████████████░ 96.0% 7,716 / 8,037
product_analytics ███████████████████░ 96.2% 28,495 / 29,617
revenue_analytics ███████████████████░ 96.4% 1,876 / 1,946
access_control ███████████████████░ 96.4% 7,122 / 7,386
user_interviews ███████████████████░ 96.5% 2,859 / 2,963
feature_flags ███████████████████░ 96.5% 25,146 / 26,046
experiments ███████████████████░ 96.6% 33,963 / 35,146
warehouse_sources ███████████████████░ 97.2% 443,923 / 456,636
data_quality ████████████████████ 97.7% 7,592 / 7,774
links ████████████████████ 97.9% 234 / 239
security ████████████████████ 98.1% 1,258 / 1,283
metrics ████████████████████ 98.1% 4,085 / 4,166
analytics_platform ████████████████████ 98.3% 2,778 / 2,827
data_catalog ████████████████████ 98.3% 3,932 / 3,999
pulse ████████████████████ 98.5% 2,043 / 2,075
live_debugger ████████████████████ 99.2% 626 / 631
field_notes ████████████████████ 99.4% 172 / 173

Report-only. Patch coverage = changed backend lines covered vs origin/master. Sorted lowest first.
Known gaps: lines covered only by Temporal tests show as uncovered; core line numbers may drift if master changed the same file.

⚠️ MCP snapshots — 3 updated (3 modified, 0 added, 0 deleted)

Snapshots: MCP unit test snapshots updated

Changes: 3 snapshots (3 modified, 0 added, 0 deleted)

What this means:

  • Snapshots have been automatically updated to match current output

Next steps:

  • Review the changes to ensure they're intentional
  • If unexpected, investigate what caused the output to change

Review snapshot changes →

ℹ️ Docs preview — preview build triggered

Docs from this PR will be published at posthog.com.

Project Preview Updated (UTC)
posthog.com Open preview Sep 21, 2026, 1:19 PM

The preview should be ready in about 10 minutes. Open the preview at /handbook/engineering/.

✅ Hobby preview — passed

Hobby deployment smoke test passed successfully.


Run 36490602770

@trunk-io

trunk-io Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

Failed Test Failure Summary Logs
test_system_one_judge_emits_boolean_probability_without_reasoning[0.49-1.0-False-False-connection_config0-https://decisions.example.com/v1... The test failed because the system could not reach the System One endpoint due to an SSL certificate hostname mismatch error. Logs ↗︎
test_system_one_judge_emits_boolean_probability_without_reasoning[0.0-0.9-True-False-connection_config1-https://decisions.example.com/v1-c... The test failed because the system could not reach the System One endpoint due to an SSL certificate hostname mismatch error. Logs ↗︎
test_system_one_judge_emits_boolean_probability_without_reasoning[0.0-0.9-True-False-connection_config0-https://decisions.example.com/v1-e... The test failed because the system could not reach the System One endpoint due to an SSL certificate hostname mismatch error. Logs ↗︎
test_system_one_judge_emits_boolean_probability_without_reasoning[0.0-0.9-True-False-connection_config2-https://decisions.example.com/v1-e... The test failed because the system could not reach the System One endpoint due to an SSL certificate hostname mismatch error. Logs ↗︎

... and 12 more

View Full Report ↗︎ ⋅ Docs

@coderabbitai

coderabbitai Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The changes add System One as a provider for boolean evaluations. They add connection configuration, endpoint and response validation, probability-based verdicts, retry and rejection handling, and probability event data. The frontend adds connection settings, separates evaluation models from generative BYOK models, and displays probabilities in evaluation details. Provider schemas, tests, pricing, and internal documentation are also updated.

Priority: ⬇️ Low

Merge Risk: 🟠 High · up to 7cbc4

Do not merge until TypeSafe evaluations enforce the required data-use controls. Rejected requests and timeouts can also interrupt evaluations, and the remaining configuration and display concerns need resolution.

Security Architecture Review

Security architecture risk: 🟠 High · up to 7cbc4

The new evaluation path can send customer content to an external provider, but the required controls for enabling that data sharing are not established in the reviewed path. Endpoint protections and connection validation reduce other risks, but do not address that approval boundary.

Retained concerns

  • High · security · inferred: The new evaluation caller can submit customer-derived evaluation content to TypeSafe without an evidenced enforcement point for the documented experimental-data and launch opt-in policy. External rollout gating remains unverified.
Security review details

Security Blast Radius

  • inferred — Exposure follows evaluations using a configured connection, not merely connection validation: evaluation-derived content can leave the service for the official provider or a customer-configured compatible endpoint. The documented instance credential shares an account budget, while other endpoint-and-credential combinations receive separate scopes; independent session-level content coverage was not established.

Security Findings and Attack Paths

  • inferred — The retained data-exposure finding concerns the new path from customer-derived evaluation input through the service's outbound provider call without an evidenced enforcement point for the documented data-sharing policy. It does not establish that an unobserved external rollout control is absent.

Trust Boundaries and Controls

  • observed — The reviewed evaluation adapter revalidates and pins the configured destination when making the actual request, rather than relying solely on the earlier synthetic connection check. The request chain preserves the pinned session and disabled-redirect argument.

Resilience and Maintainability Implications

  • observed — Failed connection updates leave the stored configuration unchanged. On terminal evaluation errors, disabling is a team-scoped, transactional, repeat-safe transition; recording the provider-key state is a subsequent activity rather than part of that transaction.

Hardening Proposals

  • proposed — Make the documented experimental and customer-data authorization gates enforceable before evaluation content enters outbound egress, and establish their rollout and approval state before launch.
  • proposed — Keep URL validation and pinning owned by the shared outbound boundary if additional production callers adopt its configurable System One entrypoint; the reviewed evaluation caller already supplies those controls.
🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description is complete and stand-alone. It covers the problem, user-visible changes, flow diagrams, screenshots, testing, release status, documentation, and agent context. The agent section does …
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Comment @coderabbitai help to get the list of available commands.

@bernatixer bernatixer changed the title feat(aio): add Jev boolean evaluations with TypeSafe keys feat(aio): add system one boolean judges with custom endpoints Sep 25, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: PostHog/posthog/.coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: aec83079-1dab-4875-86b3-07e43d775502

📥 Commits

Reviewing files that changed from the base of the PR and between 98cf112 and 25623e9.

⛔ Files ignored due to path filters (3)
  • products/ai_observability/frontend/generated/api.schemas.ts is excluded by !**/generated/**
  • products/ai_observability/frontend/generated/api.zod.ts is excluded by !**/generated/**
  • services/mcp/src/generated/ai_observability/api.ts is excluded by !**/generated/**
📒 Files selected for processing (36)
  • docs/internal/ai-observability-judge-inputs.md
  • posthog/settings/web.py
  • posthog/temporal/ai_observability/eval_reports/report_agent/prompts.py
  • posthog/temporal/ai_observability/evaluation_errors.py
  • posthog/temporal/ai_observability/evaluation_llm_judge.py
  • posthog/temporal/ai_observability/evaluation_types.py
  • posthog/temporal/ai_observability/evaluation_workflow_activities.py
  • posthog/temporal/ai_observability/test_run_evaluation.py
  • products/ai_observability/backend/api/evaluation_config.py
  • products/ai_observability/backend/api/evaluations.py
  • products/ai_observability/backend/api/provider_keys.py
  • products/ai_observability/backend/api/proxy.py
  • products/ai_observability/backend/api/taggers.py
  • products/ai_observability/backend/api/test/test_evaluations.py
  • products/ai_observability/backend/api/test/test_provider_keys.py
  • products/ai_observability/backend/llm/client.py
  • products/ai_observability/backend/llm/system_one.py
  • products/ai_observability/backend/llm/test/test_system_one.py
  • products/ai_observability/backend/models/model_configuration.py
  • products/ai_observability/backend/models/provider_keys.py
  • products/ai_observability/frontend/ConversationDisplay/EvaluationDisplay.tsx
  • products/ai_observability/frontend/components/GenerationEvalRunsTable.tsx
  • products/ai_observability/frontend/evaluations/AIObservabilityEvaluation.tsx
  • products/ai_observability/frontend/evaluations/components/EvaluationRunsTable.tsx
  • products/ai_observability/frontend/evaluations/types.ts
  • products/ai_observability/frontend/modelPickerLogic.test.ts
  • products/ai_observability/frontend/settings/LLMProviderKeysSettings.tsx
  • products/ai_observability/frontend/settings/SystemOneConnectionFields.stories.tsx
  • products/ai_observability/frontend/settings/SystemOneConnectionFields.tsx
  • products/ai_observability/frontend/settings/llmProviderKeysLogic.test.ts
  • products/ai_observability/frontend/settings/llmProviderKeysLogic.ts
  • products/ai_observability/frontend/utils.test.ts
  • products/ai_observability/frontend/utils.ts
  • services/mcp/src/api/generated.ts
  • services/mcp/tests/unit/__snapshots__/tool-schemas/llma-evaluation-create.json
  • services/mcp/tests/unit/__snapshots__/tool-schemas/llma-evaluation-update.json

Included review availability: Your plan provides up to 12 included reviews per hour; 7 remain after this review.

Comment thread posthog/temporal/ai_observability/evaluation_errors.py Outdated
Comment thread posthog/temporal/ai_observability/evaluation_llm_judge.py Outdated
@bernatixer bernatixer changed the title feat(aio): add system one boolean judges with custom endpoints feat(aio): add system one boolean and numeric judges Sep 25, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (1)
products/ai_observability/backend/llm/system_one.py-160-171 (1)

160-171: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Classify 408 as a temporary failure, not a permanent rejection.

At Line 168, the catch-all branch sends HTTP 408 (Request Timeout) to SystemOneRequestRejectedError. The PR says a rejected request stops the evaluation and requires connection revalidation. A 408 means the request timed out, and proxies and load balancers can return it for temporary reasons. With the current mapping, one timed-out request stops a healthy evaluation until a user revalidates the connection. Add 408 to the retryable branch.

🐛 Proposed fix
-        if response.status_code in (429, 503, 529):
+        if response.status_code in (408, 429, 503, 529):
             raise SystemOneRateLimitError(response.headers.get("Retry-After"))

Based on learnings: "Treat HTTP 429, 529, 5xx, and network/transient failures as retryable; treat ... permanent client errors (400, 401, 403, 404, 413) as non-retryable."

Source: Learnings

🧹 Nitpick comments (1)
products/ai_observability/frontend/settings/SystemOneConnectionFields.tsx (1)

15-15: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a data-attr to the advanced-configuration toggle.

The <summary> is the interactive control for the connection fields. Give it a stable kebab-case data-attr for autocapture and Playwright selectors. As per coding guidelines, “New buttons and key interactive elements get a kebab-case data-attr.”

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: PostHog/posthog/.coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: 3ddc84af-4c67-46dc-be18-723a6e2f4942

📥 Commits

Reviewing files that changed from the base of the PR and between 25623e9 and b773d3b.

⛔ Files ignored due to path filters (3)
  • products/ai_observability/frontend/generated/api.schemas.ts is excluded by !**/generated/**
  • products/ai_observability/frontend/generated/api.zod.ts is excluded by !**/generated/**
  • services/mcp/src/generated/ai_observability/api.ts is excluded by !**/generated/**
📒 Files selected for processing (29)
  • docs/internal/ai-observability-judge-inputs.md
  • posthog/settings/web.py
  • posthog/temporal/ai_observability/eval_reports/report_agent/prompts.py
  • posthog/temporal/ai_observability/evaluation_llm_judge.py
  • posthog/temporal/ai_observability/test_run_evaluation.py
  • products/ai_observability/backend/api/evaluations.py
  • products/ai_observability/backend/api/proxy.py
  • products/ai_observability/backend/api/test/test_evaluations.py
  • products/ai_observability/backend/llm/system_one.py
  • products/ai_observability/backend/llm/test/test_system_one.py
  • products/ai_observability/backend/models/evaluation_configs.py
  • products/ai_observability/backend/models/provider_keys.py
  • products/ai_observability/backend/models/test/test_evaluation_configs.py
  • products/ai_observability/frontend/components/EvaluationExplanation.tsx
  • products/ai_observability/frontend/evaluations/AIObservabilityEvaluation.tsx
  • products/ai_observability/frontend/evaluations/components/NumericEvaluationConfig.stories.tsx
  • products/ai_observability/frontend/evaluations/components/NumericEvaluationConfig.test.tsx
  • products/ai_observability/frontend/evaluations/components/NumericEvaluationConfig.tsx
  • products/ai_observability/frontend/evaluations/constants.ts
  • products/ai_observability/frontend/evaluations/llmEvaluationLogic.test.ts
  • products/ai_observability/frontend/evaluations/llmEvaluationLogic.ts
  • products/ai_observability/frontend/modelPickerLogic.test.ts
  • products/ai_observability/frontend/settings/SystemOneConnectionFields.tsx
  • products/ai_observability/frontend/settings/llmProviderKeysLogic.test.ts
  • products/ai_observability/frontend/settings/llmProviderKeysLogic.ts
  • services/mcp/src/api/generated.ts
  • services/mcp/tests/unit/__snapshots__/tool-schemas/llma-evaluation-create.json
  • services/mcp/tests/unit/__snapshots__/tool-schemas/llma-evaluation-test-hog.json
  • services/mcp/tests/unit/__snapshots__/tool-schemas/llma-evaluation-update.json

Included review availability: Your plan provides up to 12 included reviews per hour; 10 remain after this review.

@bernatixer bernatixer changed the title feat(aio): add system one boolean and numeric judges feat(aio): add generic system one client and jev judges Sep 25, 2026
@bernatixer bernatixer changed the title feat(aio): add generic system one client and jev judges feat(aio): add system one boolean judges with shared egress Sep 25, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (1)
services/mcp/src/api/generated.ts-38325-38325 (1)

38325-38325: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Correct the /v1 guidance for custom endpoints.

Both descriptions imply that every System One base URL must include /v1. The client accepts other HTTPS paths and appends /systemone; /v1 is part of the TypeSafe default, not a universal requirement. A client following this guidance can submit the wrong URL and fail connection validation. Update the serializer help text and regenerate both descriptions. (raw.githubusercontent.com)

Also applies to: 73670-73670


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: PostHog/posthog/.coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: e7c9dd2c-5b92-496e-820e-641522966aa9

📥 Commits

Reviewing files that changed from the base of the PR and between 81ea2bb and 7cbc470.

⛔ Files ignored due to path filters (3)
  • products/ai_observability/frontend/generated/api.schemas.ts is excluded by !**/generated/**
  • products/ai_observability/frontend/generated/api.zod.ts is excluded by !**/generated/**
  • services/mcp/src/generated/ai_observability/api.ts is excluded by !**/generated/**
📒 Files selected for processing (12)
  • docs/internal/ai-observability-judge-inputs.md
  • posthog/egress/test/test_typesafe.py
  • posthog/egress/typesafe/README.md
  • posthog/egress/typesafe/client.py
  • posthog/egress/typesafe/limiter.py
  • posthog/egress/typesafe/transport.py
  • posthog/temporal/ai_observability/evaluation_llm_judge.py
  • posthog/temporal/ai_observability/test_run_evaluation.py
  • products/ai_observability/backend/api/test/test_provider_keys.py
  • products/ai_observability/backend/llm/system_one.py
  • products/ai_observability/backend/llm/test/test_system_one.py
  • services/mcp/src/api/generated.ts

Included review availability: Your plan provides up to 12 included reviews per hour; 9 remain after this review.

Comment thread posthog/egress/typesafe/README.md Outdated
@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

🦔 Hogbox preview · ✅ ready

▶ Open the preview

🔑 Login test@posthog.com / 12345678 (demo data)
🧩 Running this PR's backend and frontend, on the PostHog :master base
🔗 Link stable across rebuilds — a re-push swaps the box underneath, the URL stays
🔒 Access tailnet only (PostHog VPN)
🛠️ Admin inspect & debug state in hogland
💤 Idle sleeps after ~30 min idle (snapshot to S3, zero node cost) and wakes on your next visit in ~30s, behind a brief "waking up" screen

commit 8484b39 · box box-9603b478e0cf · ready in 708s (push → usable) · build log · rebuilds on every push, torn down on close

@pr-assigner-resolver-posthog
pr-assigner-resolver-posthog Bot requested review from a team September 28, 2026 08:23
@pr-assigner-resolver-posthog

Copy link
Copy Markdown

👀 Auto-assigned reviewers

These soft owners were skipped because they only have minor changes here. Nothing blocks merge, so self-assign if you'd like a look:

  • @PostHog/team-product-analytics (posthog/owners.yaml)

Soft owners come from each directory's owners.yaml and each product's product.yaml (resolved nearest-file-wins). The locator after each owner is the file that decided it. Generated files and lockfiles are ignored when deciding ownership.

Comment thread posthog/egress/typesafe/client.py Outdated
@veria-ai

veria-ai Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

PR overview

All previously flagged issues have been addressed. No open security concerns remain on this pull request.

Security review

No open security issues remain on this pull request.

Fixed/addressed: 1 · PR risk: 0/10

@posthog

posthog Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

✅ Visual changes approved by @bernatixer — baseline updated in 177e3c3.

View this run in PostHog

14 new.

14 updated
Run: bab2187e-6b2d-47cf-b768-f422efd58273

Co-authored-by: bernatixer <2202231+bernatixer@users.noreply.github.com>
Comment thread posthog/egress/typesafe/client.py Outdated
priority=priority,
timeout=timeout,
allow_redirects=False,
stream=True,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requests consumes redirect bodies even with stream=True and allow_redirects=False, before these limits run. Can we do something about it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added _prevent_redirect_body_read function for this

}

const handleApiKeyBlur = (): void => {
if (isSystemOne) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why skip it?

@bernatixer bernatixer Sep 28, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this skips only the on-blur, key check for SystemOne as we might receive a no key and this endpoint requires a key (and also doesn't accept a base URL, which we need in this case). The validation is still being applied at submit

Comment thread posthog/egress/typesafe/client.py Outdated
body = bytearray()
# boffin: Check each byte so a trickling endpoint cannot keep a larger read open indefinitely.
for chunk in response.iter_content(chunk_size=1):
if monotonic() >= deadline or len(body) + len(chunk) > MAX_RESPONSE_BYTES:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that we allow custom endpoints, a server can send headers slowly and keep an eval thread busy past 60 seconds. This deadline check only runs after the headers arrive. Could we enforce a timeout for the whole request?

@github-actions
github-actions Bot requested a deployment to preview-pr-103752 September 28, 2026 22:02 In progress

This branch was successfully deployed

1 active deployment
preview-pr-103752 — 8484b39c Deployed Sep 28, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants